﻿#include <context/basecontext.h>
#include <data/replypacket.h>
#include <data/startargs.h>
#include <data/stopargs.h>
#include <state/statefactory.h>
#include <pointer/basepointer.h>
#include <QsLog.h>

BaseContext::BaseContext(BasePointer *pointer)
    : QObject(Q_NULLPTR)
{
    m_pointer = pointer;
    m_startArgs = Q_NULLPTR;
    m_state = Q_NULLPTR;
    m_bServer = true;
}

BaseContext::BaseContext(BasePointer *pointer, const StartArgs &args)
    : QObject(Q_NULLPTR)
{
    m_pointer = pointer;
    m_startArgs = new StartArgs(args);
    m_state = Q_NULLPTR;
    m_bServer = false;
}

BaseContext::~BaseContext()
{
    if(m_state)
    {
        delete m_state;
        m_state = nullptr;
    }
    if(m_startArgs)
    {
        delete m_startArgs;
        m_startArgs = Q_NULLPTR;
    }
}

BaseState *BaseContext::state() const
{
    return m_state;
}

void BaseContext::changeState(BaseState *state)
{
    if(state == Q_NULLPTR)
    {
        QLOG_TRACE() << QObject::tr("Change final!");
    }else {
        QLOG_TRACE() << QString(QObject::tr("Change state to %1") ).arg(state->stateName());
    }

    if(m_state)
    {
        delete m_state;
        m_state = nullptr;
    }
    if(state)
    {
        m_state = state;
        m_state->process(); // 改变状态完毕后，执行当前状态。
    }else {
        this->deleteLater();  //   释放当前对象。
    }
}

BasePointer *BaseContext::pointer() const
{
    return m_pointer;
}

bool BaseContext::buildDataLink(const IPFiveTuple &args)
{
    Q_ASSERT(m_pointer);
    return m_pointer->buildDataLink(args);
}

void BaseContext::add(PointerCallback *callback)
{
    Q_ASSERT(m_pointer);
    m_pointer->add(callback);
}

void BaseContext::remove(PointerCallback *callback)
{
    Q_ASSERT(m_pointer);
    m_pointer->remove(callback);
}

void BaseContext::disConnect(bool bCmd)
{
    Q_ASSERT(m_pointer);
    m_pointer->disConnect(bCmd);
}

void BaseContext::close(bool bCmd)
{
    Q_ASSERT(m_pointer);
    m_pointer->close(bCmd);
}

bool BaseContext::start()
{
    if(!m_startArgs)
    {
        return false;
    }
    Q_ASSERT(m_pointer);
    StartArgs args = *m_startArgs;
    IPFiveTuple tuple = args.ipTuple();
    if(m_pointer->buildDataLink(tuple)) // 建立数据链路。
    {
        tuple.reverse();
        args.setIpTuple(tuple);  // 反转后通过指令链路发送到远端。
        return m_pointer->start(args);
    }else {
        QLOG_WARN() << QObject::tr("build datalink failed, ");
        return false;
    }
}

void BaseContext::init(const InitArgs &args)
{
    if(m_state)
    {
        delete m_state;
    }
    BaseState::StateType type = m_bServer ?
                BaseState::InitServer : BaseState::InitClient;
    StateFactory factory(type, m_bServer);
    m_state = factory.create(this);
    m_state->process();
    m_pointer->init(args);
}

bool BaseContext::request(const RequestPacket &pack)
{
    Q_ASSERT(m_pointer);
    m_pointer->request(pack);
    return true;
}

bool BaseContext::reply(const ReplyPacket &pack)
{
    Q_ASSERT(m_pointer);
    m_pointer->reply(pack);
    return true;
}

bool BaseContext::ready()
{
    Q_ASSERT(m_pointer);
    m_pointer->ready();
    return true;
}

void BaseContext::stop(const StopArgs &args)
{
    Q_ASSERT(m_pointer);

    QLOG_INFO() << QString(QObject::tr("Receive stop %1")).arg(args.toString());
    m_pointer->stop(args);
}

StartArgs *BaseContext::startArgs() const
{
    return m_startArgs;
}
